using System;
using System.Collections.Generic;

using IBatisNet.Common;
using IBatisNet.DataMapper;

using log4net;

using GymManager.Exception;
using GymManager.Persistence.VO;

namespace GymManager.Persistence.DAO
{
    /// <summary>
    /// Class responsible by getting information from database about students
    /// </summary>
    public class StudentDAO
    {
        // logger instance
        private ILog _logManager = LogManager.GetLogger(typeof(StudentDAO));

        /// <summary>
        /// Method responsible by getting an student by its name
        /// </summary>
        /// <param name="String">student's login</param>
        /// <returns>Student - student retrieved in according to student's name</returns>
        public Student findByName(String name)
        {
            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("Begin Method");
            }

            // user value object to be returned
            Student studentResult = null;

            try
            {
                ISqlMapper ibatisMapper = DAOManager.getInstance();
                studentResult = ibatisMapper.QueryForObject<Student>("Student.findByName", name);
            }
            catch (System.Exception ex)
            {
                _logManager.Error("Error while retrieving student information", ex);
                throw new PersistenceException("Error while retrieving student information", ex);
            }

            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("End Method");
            }

            return studentResult;
        }

        /// <summary>
        /// Method responsible by getting all active students 
        /// </summary>
        /// <returns>IList - list of all active students</returns>
        public IList<Student> findAllActive()
        {
            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("Begin Method");
            }

            // student list
            IList<Student> studentList = null;

            try
            {
                ISqlMapper ibatisMapper = DAOManager.getInstance();
                studentList = ibatisMapper.QueryForList<Student>("Student.findAllActive", null);
            }
            catch (System.Exception ex)
            {
                _logManager.Error("Error while retrieving student information", ex);
                throw new PersistenceException("Error while retrieving student information", ex);
            }

            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("End Method");
            }

            return studentList;
        }

        /// <summary>
        /// Method responsible by finding students using any of its properties
        /// </summary>
        /// <param name="Student">student vo</param>
        /// <returns>IList - list of students retrieved in according to filter</returns>
        /// <see cref="GymManager.Exception.PersistenceException"/>
        public IList<Student> findByAny(Student studentVOFilter)
        {
            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("Begin Method");
            }

            // list of students found
            IList<Student> studentList = null;

            try
            {
                ISqlMapper ibatisMapper = DAOManager.getInstance();
                studentList = ibatisMapper.QueryForList<Student>("Student.findByAny", studentVOFilter);
            }
            catch (System.Exception ex)
            {
                _logManager.Error("Error while retrieving student information", ex);
                throw new PersistenceException("Error while retrieving student information", ex);
            }

            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("End Method");
            }

            return studentList;
        }

        /// <summary>
        /// Method responsible by adding a new student to database
        /// </summary>
        /// <param name="Student">student information to be saved</param>
        /// <see cref="GymManager.Exception.PersistenceException"/>
        public void create(Student studentVO)
        {
            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("Begin Method");
            }

            try
            {
                ISqlMapper ibatisMapper = DAOManager.getInstance();

                // doing job inside transaction
                using (IDalSession sessionTransaction = ibatisMapper.BeginTransaction())
                {
                    // inserting a new student
                    ibatisMapper.Insert("Student.insert", studentVO);

                    // inserting all medicam exam
                    if (studentVO.MedicalExamList != null && studentVO.MedicalExamList.Count > 0)
                    {
                        foreach (MedicalExam medicalExam in studentVO.MedicalExamList)
                        {
                            // assigning student id
                            medicalExam.StudentId = studentVO.Id;

                            // adding medical exam
                            ibatisMapper.Insert("MedicalExam.insert", medicalExam);
                        }
                    }

                    // inserting all student's modalities
                    if (studentVO.StudentModalityList != null && studentVO.StudentModalityList.Count > 0)
                    {
                        foreach (StudentModality studentModality in studentVO.StudentModalityList)
                        {
                            // assigning student id
                            studentModality.StudentId = studentVO.Id;

                            // adding student modality
                            ibatisMapper.Insert("StudentModality.insert", studentModality);

                            // inserting all information regarding student's modalitis schedule
                            if (studentModality.StudentModalityScheduleList != null && studentModality.StudentModalityScheduleList.Count > 0)
                            {
                                foreach (StudentModalitySchedule modalitySchedule in studentModality.StudentModalityScheduleList)
                                {
                                    // assigning student id
                                    modalitySchedule.StudentModalityId = studentModality.Id;

                                    // adding student modality
                                    ibatisMapper.Insert("StudentModalitySchedule.insert", modalitySchedule);
                                }
                            }
                        }
                    }

                    // commit the transaction
                    sessionTransaction.Complete();
                }
            }
            catch (System.Exception ex)
            {
                _logManager.Error("Error while saving student information", ex);
                throw new PersistenceException("Error while saving student information", ex);
            }

            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("End Method");
            }
        }

        /// <summary>
        /// Method responsible by updating student information into database
        /// </summary>
        /// <param name="Student">student information to be saved</param>
        /// <see cref="GymManager.Exception.PersistenceException"/>
        public void update(Student studentVO)
        {
            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("Begin Method");
            }

            try
            {
                ISqlMapper ibatisMapper = DAOManager.getInstance();

                // doing job inside transaction
                using (IDalSession sessionTransaction = ibatisMapper.BeginTransaction())
                {
                    // update student information
                    ibatisMapper.Update("Student.update", studentVO);

                    // deleting exam information
                    ibatisMapper.Delete("MedicalExam.deleteByStudent", studentVO.Id);

                    // deleting modality schedule information
                    ibatisMapper.Delete("StudentModalitySchedule.deleteByStudent", studentVO.Id);
                    
                    // deleting modality information
                    ibatisMapper.Delete("StudentModality.deleteByStudent", studentVO.Id);

                    // inserting all medicam exam
                    if (studentVO.MedicalExamList != null && studentVO.MedicalExamList.Count > 0)
                    {
                        foreach (MedicalExam medicalExam in studentVO.MedicalExamList)
                        {
                            // assigning student id
                            medicalExam.StudentId = studentVO.Id;

                            // adding medical exam
                            ibatisMapper.Insert("MedicalExam.insert", medicalExam);
                        }
                    }

                    // inserting all student's modalities
                    if (studentVO.StudentModalityList != null && studentVO.StudentModalityList.Count > 0)
                    {
                        foreach (StudentModality studentModality in studentVO.StudentModalityList)
                        {
                            // assigning student id
                            studentModality.StudentId = studentVO.Id;

                            // adding student modality
                            ibatisMapper.Insert("StudentModality.insert", studentModality);

                            // inserting all information regarding student's modalities schedule
                            if (studentModality.StudentModalityScheduleList != null && studentModality.StudentModalityScheduleList.Count > 0)
                            {
                                foreach (StudentModalitySchedule modalitySchedule in studentModality.StudentModalityScheduleList)
                                {
                                    // assigning student id
                                    modalitySchedule.StudentModalityId = studentModality.Id;

                                    // adding student modality
                                    ibatisMapper.Insert("StudentModalitySchedule.insert", modalitySchedule);
                                }
                            }
                        }
                    }

                    // committing the transaction
                    sessionTransaction.Complete();
                }
            }
            catch (System.Exception ex)
            {
                _logManager.Error("Error while saving student information", ex);
                throw new PersistenceException("Error while saving student information", ex);
            }

            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("End Method");
            }
        }
    }
}
